package mirabilis.samples.cec2014;

import mirabilis.org.IEvaluator;
import mirabilis.org.config.Configuration;
import mirabilis.org.simplices.Coordinates;
import mirabilis.org.simplices.Vertex;
import mirabilis.org.termination.Termination;



public class Cec2014 implements IEvaluator{
	
	//For each of the 30 functions
	public static double[] optima = new double[] 
	{	
		100,200,300,400,500,600,700,800,900,1000,
		1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,
		2100,2200,2300,2400,2500,2600,2700,2800,2900,3000
	};
	
	public static long maxFEs = 10000*Configuration.N;
	
	//0.01 x 10000D = 100D, 0.02 x ....
	public static double[] record14prints = new double[]{
		100*Configuration.N, 200*Configuration.N, 300*Configuration.N, 500*Configuration.N,
		1000*Configuration.N, 2000*Configuration.N, 3000*Configuration.N, 4000*Configuration.N, 
		5000*Configuration.N, 6000*Configuration.N, 7000*Configuration.N, 8000*Configuration.N,
		9000*Configuration.N, 10000*Configuration.N
	};
	
	public static int nextcec2014print = 0; //initialize the counter for records
	
	private testfunc tf;
	
	public Cec2014() {
		tf = new testfunc();
		Configuration.termination_max_evaluation = maxFEs; 
		/*
		// Copy/paste/alter the following code where necessary to keep record of the printing
			if(nextcec2014print < record14prints.length && record14prints[nextcec2014print] >= Termination.get_n_evaluation()){
				//Call command for printing
				nextcec2014print++;// increase the record count for the next printing call
			}
		*/
	}

	// The fitness is evaluated as the error
	public double evaluate(double[] x){
		int func_num = Configuration.F;
		
		if(func_num==0){// This 'if' is just a hack to define the sphere function when F=0
			return sphere(x);
		}else if(func_num==-1){
			return concave(x);
		}else if(func_num==-2){
			return concave_semi_definite(x);
		}else{
			double[] f = new double[1];
			try {
				tf.test_func(x,f,x.length,1,func_num);
			} catch (Exception e) {
				e.printStackTrace();
			}
			double error = f[0]-optima[func_num-1];

			return error;		
		}
	}
	
	private double sphere(double[] x){
		double y=0;
		for(int i=0;i<x.length;i++){
			y += Math.pow(x[i]-50, 2);
		}
		return y;
	}
	
	private double concave(double[] x){
		double y=0;
		for(int i=0;i<x.length;i++){
			y += Math.log10(Math.pow(x[i]-50, 2)+1);
		}
		return y;
	}
	
	private double concave_semi_definite(double[] x){
		double y=Math.log10(Math.pow(x[0]+50, 2)+1); // In this dimension is concave
		
		for(int i=1;i<x.length;i++){
			y += Math.abs(x[i]);
		}
		return y;
	}
	
	public double hit_value() {//the problem is minimizing the error 
		return 0;
	}
	
	public Object clone() {
		Cec2014 pp = new Cec2014();
		return pp;
	}
	
	
	public static void main(String[] args) {
		Configuration.F=2;
		Configuration.N=2;
		Configuration.upper_bound= 200;
		Configuration.lower_bound= -200;
		double step = (Configuration.upper_bound - Configuration.lower_bound) / 200.0;
		
		Cec2014 bench = new Cec2014();
		
		double minfitness = Double.MAX_VALUE;
		double pos_1=0,pos_2=0;
		
		//step = 100;
		
		for (double i=Configuration.lower_bound; i<=Configuration.upper_bound;i+=step){
			for (double j=Configuration.lower_bound; j<=Configuration.upper_bound;j+=step){
				double[] genes = new double[Configuration.N];
				for(int h=0;h<Configuration.N;h+=2){
					genes[h] = i;
					genes[h+1] = j;
				}
				Coordinates chromo = new Coordinates(genes);
				Vertex ind = new Vertex(chromo);
				
				
				
				double fit = bench.evaluate(ind.getCoordinates().getCoordinatesAsDouble());
				if(fit < minfitness){
					minfitness = fit;
					pos_1 = i;
					pos_2 = j;
				}
				ind.setFitness(fit);
				try {
					System.out.println(i+" "+j+" "+fit+" ");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
					
			System.out.println("");	
		}
		
		System.err.println("pos: "+pos_1+","+pos_2+" fit: "+minfitness);
		
//		for (double i=Configuration.lower_bound; i<=Configuration.upper_bound;i+=step){
//			double[] genes = new double[Configuration.N];
//			for(int j=0;j<Configuration.N;j++){
//				genes[j] = i;
//			}
//			DoubleChromosome chromo = new DoubleChromosome(genes);
//			Individual ind = new DoubleIndividual(chromo);
//			
//			
//			
//			bench.evaluate(ind);
//			double[] d = ind.getChr().asdouble();
//			for(int j=0;j<Configuration.N;j++){
//				System.out.print(d[j]+" ");
//			}
//			
//			System.out.println(""+ind.getFitness());	
//		}
		
	}
}
